package com.aplink.generic.widgets;

import java.util.ArrayList;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.Spinner;

import com.aplink.generic.GenericFragment;
import com.aplink.generic.adapter.ConfigAdapter;
import com.aplink.generic.cache.ContentDataManager;
import com.aplink.generic.database.SqlMethods;
import com.aplink.generic.dictionary.GenericDictionary;
import com.aplink.generic.interfaces.OnGetObjProInfo;
import com.aplink.generic.pojo.ColumnSetting;
import com.aplink.generic.pojo.ContentData;
import com.aplink.generic.pojo.GenericAttribute;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.pojo.Value;
import com.aplink.generic.pojo.controlspec.ControlSpec;
import com.aplink.generic.pojo.controlspec.spinner.SpinnerSpec;
import com.aplink.generic.util.ResourcesHelper;
import com.aplink.generic.util.validation.ValidationResult;
import com.aplink.generic.xmlparser.ColumnSettingParser;

public class ApLinkSpinner extends ApLinkBaseView implements OnClickListener,
        OnItemSelectedListener, OnGetObjProInfo {
	private ArrayList<ColumnSetting> columnSettings;
	private BaseAdapter mBaseAdapter;
	private ContentData mContentData;
	private String mDefaultValue;
	private GenericDictionary<String, GenericAttribute> mListAttribute;
	private ArrayList<GenericObject> mListObjects;
	private Spinner mSpinner;
	private final SpinnerSpec mSpinnerSpec;

	public ApLinkSpinner(final GenericFragment dataEntryActivity,
	        final ControlSpec controlSpec, final View view, Bundle bundle) {
		super(dataEntryActivity, controlSpec, view, bundle);
		setSpinner((Spinner) view);
		this.mSpinnerSpec = (SpinnerSpec) controlSpec;
		this.mContentData = new ContentData();
		this.mListObjects = new ArrayList<GenericObject>();
	}

	private void addNewItemRecord() {
		final GenericObject genericObject = new GenericObject();
		genericObject.put(this.mSpinnerSpec.getDataObject() + "."
		        + this.mSpinnerSpec.getDisplayProperty(),
		        this.mSpinnerSpec.getNewRowItem());
		this.mListObjects.add(genericObject);
	}

	private void addToFirst(final String value) {
		final GenericObject genericObject = new GenericObject();
		genericObject.put(this.mSpinnerSpec.getDataObject() + "."
		        + this.mSpinnerSpec.getDisplayProperty(), value);
		final ArrayList<GenericObject> arrayList = new ArrayList<GenericObject>();
		arrayList.add(genericObject);
		arrayList.addAll(this.mListObjects);
		this.mListObjects = arrayList;
		setAdapet();
		this.mSpinner.setAdapter(this.mBaseAdapter);
		this.mSpinner.setSelection(0);
	}

	@Override
	public void clear() {

	}

	private ConfigAdapter generateConfigAdapter() {
		this.columnSettings = ColumnSettingParser.parse(getGenericFragment(),
		        this.mSpinnerSpec.getRptrdesignID());
		final ConfigAdapter configAdapter = new ConfigAdapter(
		        getGenericFragment(), this.mListObjects, this.columnSettings,
		        this.mSpinnerSpec.getRowItem());
		return configAdapter;
	}

	@Override
	public GenericAttribute getAttribute() {
		final ObjPropInfo primaryKey = this.mContentData.getPrimaryKeys()
		        .get(0);
		final String columnNameContentData = primaryKey.getFullColumnName();
		final ObjPropInfo objPropInfo = this.mContentData
		        .get(columnNameContentData);
		final int selectedPosition = this.mSpinner.getSelectedItemPosition();
		if (selectedPosition >= 0 && selectedPosition < mListObjects.size()) {
			final GenericObject genericObject = this.mListObjects
			        .get(selectedPosition);
			return GenericAttribute.obtain(
			        genericObject.getValue(columnNameContentData), objPropInfo);
		}
		return GenericAttribute.obtain(null, objPropInfo);
	}

	public String getDefaultValue() {
		return this.mDefaultValue;
	}

	@Override
	public GenericDictionary<String, GenericAttribute> getListAttributes() {
		return this.mListAttribute;
	}

	@Override
	public ObjPropInfo getObjProInfoTemp() {
		final String databObj = ApLinkSpinner.this.mValueList.getDataObj();
		final String mappingName = ApLinkSpinner.this.getSelectedMappingName();
		return ApLinkSpinner.this.getGenericFragment().getContentData()
		        .get(databObj + "." + mappingName);
	}

	public GenericObject getSelectedItem() {
		final int index = this.mSpinner.getSelectedItemPosition();
		return this.mListObjects.get(index);
	}

	private String getSelectedMappingName() {
		final int selectedIndex = this.mSpinner.getSelectedItemPosition();
		final GenericObject selectedObject = this.mListObjects
		        .get(selectedIndex);
		final String valueColumn = this.mValueList.getValueColumn();
		final String value = selectedObject.getValue(valueColumn).toString();
		return this.mValueList.get(value).getMappingName();
	}

	public String getSelectedValue() {
		return this.mSpinner.getSelectedItem().toString();
	}

	private String getSelectWhereValue(final String key) {
		return getPassedObject().getValue(key);
	}

	public Spinner getSpinner() {
		return this.mSpinner;
	}

	@Override
	public Spinner getView() {
		return this.mSpinner;
	}

	@Override
	protected void initViewProperties() {
		final boolean isVisibility = this.mSpinnerSpec.isVisibility();
		if (!isVisibility) {
			this.mSpinner.setVisibility(View.GONE);
		}
		this.mSpinner.setTag(this.mSpinnerSpec);

		if (this.mContentData.isEmpty()) {
			this.mContentData = ContentDataManager.getInstance().get(
			        this.mSpinnerSpec.getContentDataID());
		}

		if (hasValueList()) {
			this.mListAttribute = new GenericDictionary<String, GenericAttribute>();
		}
	}

	@Override
	public void languageChanged() {
		// TODO Auto-generated method stub

	}

	@Override
	protected void loadBindingObject() {
		if (TextUtils.isEmpty(this.mSpinnerSpec.getFilterBy())) {
			this.mListObjects = loadData(getRefreshConditions());
		} else {
			final String selectWhere[] = this.mSpinnerSpec.getFilterBy().split(
			        ";");
			final SqlMethods whereClause = SqlMethods.getInstance();
			for (int i = 0; i < selectWhere.length; i++) {
				final String solumnName = selectWhere[i];
				whereClause.equal(solumnName, getSelectWhereValue(solumnName));
				if (i < (selectWhere.length - 1)) {
					whereClause.and();
				}
			}
			this.mListObjects = loadData(whereClause.toString());
		}

		if (mListObjects.isEmpty()) {
			return;
		}

		final String mappingName = this.mSpinnerSpec.getDataObject() + "."
		        + this.mSpinnerSpec.getMappingName();
		final String selectedValue = getPassedObject().getValue(mappingName);
		final String selectedColumn = String.format("%s.%s", this.mListObjects
		        .get(0).getTableName(), this.mSpinnerSpec.getMappingName());
		int index = -1;
		for (int i = 0; i < this.mListObjects.size(); i++) {
			final GenericObject genericObject = this.mListObjects.get(i);
			final String value = genericObject.getValue(selectedColumn)
			        .toString();
			if (value.equalsIgnoreCase(selectedValue)) {
				index = i;
				break;
			}
		}
		if (this.mListObjects != null) {
			if (this.mSpinnerSpec.getRptrdesignID() == ResourcesHelper.RESOURCE_NOT_FOUND) {
				setAdapet();
			} else {
				this.mBaseAdapter = generateConfigAdapter();
			}
		}
		if (hasValueList()) {
			// mValueList
			final String dataObj = this.mValueList.getDataObj();
			for (int i = 0; i < this.mValueList.size(); i++) {
				final Value value = this.mValueList.valueAt(i);
				final String columnName = dataObj + "."
				        + value.getMappingName();
				final String realValue = getPassedObject().getValue(columnName);
				final ObjPropInfo objPropInfo = getGenericFragment()
				        .getContentData().get(columnName);
				final GenericAttribute attribute = GenericAttribute.obtain(
				        realValue, objPropInfo);
				this.mListAttribute.put(columnName, attribute);
			}
		}
		mergeStaticResource();
		this.mSpinner.setAdapter(this.mBaseAdapter);

		if (this.mSpinnerSpec.isHasNewRowItem()) {
			if (index == -1) {
				addToFirst(selectedValue);
				this.mSpinner.setSelection(0);
			}
		} else {
			this.mSpinner.setSelection(index);
		}
	}

	protected ArrayList<GenericObject> loadData(final String whereConditions) {
		this.mListObjects = getDatabaseGet().getList(this.mContentData,
		        whereConditions);
		if (this.mSpinnerSpec.isHasNewRowItem()) {
			addNewItemRecord();
		}
		if (hasValueList()) {
			mergeStaticResource();
		}
		return this.mListObjects;
	}

	@Override
	protected void loadDefaultObject() {
		if (TextUtils.isEmpty(this.mSpinnerSpec.getFilterBy())) {
			this.mListObjects = loadData(getRefreshConditions());
		} else {
			final String selectWhere[] = this.mSpinnerSpec.getFilterBy().split(
			        ";");
			final SqlMethods whereClause = SqlMethods.getInstance();
			for (int i = 0; i < selectWhere.length; i++) {
				final String solumnName = selectWhere[i];
				whereClause.equal(solumnName, getSelectWhereValue(solumnName));
				if (i < (selectWhere.length - 1)) {
					whereClause.and();
				}
			}
			this.mListObjects = loadData(whereClause.toString());
		}

		if (this.mListObjects != null) {
			if (this.mSpinnerSpec.getRptrdesignID() == ResourcesHelper.RESOURCE_NOT_FOUND) {
				setAdapet();
			} else {
				this.mBaseAdapter = generateConfigAdapter();
			}
		}
		this.mSpinner.setAdapter(this.mBaseAdapter);
	}

	private void mergeStaticResource() {
		if (hasValueList()) {
			final String dataObj = this.mValueList.getDataObj();
			final String column = this.mValueList.getValueColumn();
			for (int i = 0; i < this.mListObjects.size(); i++) {
				final GenericObject object = this.mListObjects.get(i);
				final String value = object.get(column).getValue().toString();
				final String mappingName = this.mValueList.get(value)
				        .getMappingName();
				final GenericAttribute attribute = this.mListAttribute
				        .get(dataObj + "." + mappingName);
				object.put(ColumnSetting.STATIC_RESOURCE, attribute);
			}
		}
	}

	@Override
	public void onClick(final View v) {
		final ControlSpec controlSpec = (ControlSpec) v.getTag();
		final ValidationResult result = ApLinkSpinner.this.getGenericFragment()
		        .isFormValidate(controlSpec);
		if (result.isValid()) {
			String value = null;
			final View valueControl = ApLinkSpinner.this.getValueControl();
			if (valueControl instanceof EditText) {
				value = ((EditText) valueControl).getText().toString();
			}
			final String dataObj = ApLinkSpinner.this.mValueList.getDataObj();
			final String mappingName = ApLinkSpinner.this
			        .getSelectedMappingName();

			final ObjPropInfo objPropInfo = ApLinkSpinner.this
			        .getGenericFragment().getContentData()
			        .get(dataObj + "." + mappingName);
			final GenericAttribute attribute = GenericAttribute.obtain(value,
			        objPropInfo);
			ApLinkSpinner.this.mListAttribute.put(dataObj + "." + mappingName,
			        attribute);
			if (ApLinkSpinner.this.hasValueList()) {
				ApLinkSpinner.this.mergeStaticResource();
				ApLinkSpinner.this.mBaseAdapter.notifyDataSetChanged();
			}
			((EditText) valueControl).getText().clear();
		} else {
			ApLinkSpinner.this.getGenericFragment()
			        .showInvalidValidationDialog(controlSpec.getActionType(),
			                result);
		}
	}

	@Override
	public void onItemSelected(final AdapterView<?> parent, final View view,
	        final int position, final long id) {
		if (ApLinkSpinner.this.mSpinnerSpec.getRefreshControl() != null) {
			final String refreshViewID = ApLinkSpinner.this.mSpinnerSpec
			        .getRefreshControl();
			final ApLinkBaseView baseView = ApLinkSpinner.this
			        .getGenericFragment().getAPLinkViewByID(refreshViewID);
			final String refreshValue = ApLinkSpinner.this.mSpinnerSpec
			        .getRefreshValue();
			final GenericAttribute selectedAttribute = ApLinkSpinner.this
			        .getAttribute();
			final SqlMethods sqlMethods = SqlMethods.getInstance();
			sqlMethods.equal(refreshValue, selectedAttribute.getValue()
			        .toString());
			baseView.setRefreshConditions(sqlMethods.toString());
			baseView.notifyDataSetChanged();
		}

		if (ApLinkSpinner.this.mSpinnerSpec.isHasNewRowItem()) {
			if (position == (ApLinkSpinner.this.mListObjects.size() - 1)) {
				final AlertDialog.Builder builder = new AlertDialog.Builder(
				        ApLinkSpinner.this.getActivity());
				final EditText editText = new EditText(
				        ApLinkSpinner.this.getActivity());
				final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(
				        LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
				editText.setLayoutParams(layoutParams);
				builder.setView(editText);
				builder.setTitle(ApLinkSpinner.this.mSpinnerSpec
				        .getNewRowItem());
				builder.setCancelable(false).setPositiveButton("OK",
				        new DialogInterface.OnClickListener() {

					        @Override
					        public void onClick(final DialogInterface dialog,
					                final int which) {
						        if (which == DialogInterface.BUTTON_POSITIVE) {
							        ApLinkSpinner.this.addToFirst(editText
							                .getText().toString());
						        }
					        }
				        });
				builder.create().show();
			}
		}
	}

	@Override
	public void onNothingSelected(final AdapterView<?> parent) {

	}

	@SuppressWarnings("unchecked")
	private void setAdapet() {
		final String[] arrTextValue = new String[this.mListObjects.size()];
		final String fullColumnName = this.mContentData.getMainTable() + "."
		        + this.mSpinnerSpec.getDisplayProperty();
		for (int i = 0; i < this.mListObjects.size(); i++) {
			final GenericObject genericObject = this.mListObjects.get(i);
			final String value = genericObject.getValue(fullColumnName)
			        .toString();
			arrTextValue[i] = value;
		}

		this.mBaseAdapter = new ArrayAdapter<String>(getActivity(),
		        android.R.layout.simple_spinner_item, arrTextValue);
		((ArrayAdapter<String>) mBaseAdapter)
		        .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	}

	private void setClickEvent(final String targetControlID,
	        final OnClickListener onClickListener) {
		ApLinkBaseView baseView = null;
		if (!TextUtils.isEmpty(targetControlID)) {
			baseView = getGenericFragment().getAPLinkViewByID(targetControlID);
			if (baseView != null) {
				baseView.setOnClickListener(onClickListener);
			} else if (getGenericFragment().getFormDesign()
			        .getControlSpecCollection().get(targetControlID) != null) {
				getGenericFragment().getFormDesign().getControlSpecCollection()
				        .get(targetControlID)
				        .setOnClickListener(onClickListener);
			} else if (getGenericFragment().findViewByID(targetControlID) != null) {
				getGenericFragment().findViewByID(targetControlID)
				        .setOnClickListener(onClickListener);
			}
		}
	}

	public void setDefaultValue(final String defaultValue) {
		this.mDefaultValue = defaultValue;
	}

	@Override
	protected void setEventListener() {
		this.mSpinner.setOnItemSelectedListener(this);
		if (hasValueList()) {
			setClickEvent(this.mValueList.getSubmitControl(), this);

			final String resultControlID = this.mValueList.getValueControl();
			final ControlSpec specValueControl = getGenericFragment()
			        .getFormDesign().getControlSpecCollection()
			        .get(resultControlID);
			specValueControl.setOnGetObjProInfo(this);
			final ApLinkBaseView resultControl = getGenericFragment()
			        .getAPLinkViewByID(resultControlID);
			if (resultControl != null) {
				resultControl.setObjPropInfoTemp(this);
			}
		}
	}

	@Override
	public void setObjPropInfoTemp(final OnGetObjProInfo getObjProInfo) {
		throw new UnsupportedOperationException(this.getClass().getSimpleName()
		        + " is not support this method");
	}

	@Override
	public void setOnClickListener(final OnClickListener onClickListener) {
		throw new UnsupportedOperationException(this.getClass().getSimpleName()
		        + " is not support this method");
	}

	public void setSpinner(final Spinner spinner) {
		this.mSpinner = spinner;
	}
}
